/**
 * Created by Dave on 2017/3/10.
 */

var express = require('express');
var router = express.Router();
var tpl=require('../node_modules/baidutemplate/baiduTemplate.js');
var jsonUtil = require('../lib/util/jsonUtil');
var appConfigEnv = require('../db/appConfigEnvDB');
var envdb = new appConfigEnv();
var appConfigFile = require('../db/appConfigFileDB');
var filedb = new appConfigFile();
var appConfigHistoryDB = require('../db/appConfigHistoryDB');
var historydb = new appConfigHistoryDB();
var appConfigSet = require('../db/appConfigSetDB');
var setdb = new appConfigSet();
var logger = require('../lib/log4js/log4js').logger('appConfigEnv');
var cmgr = require('../lib/configManager/configManager');
var myRet = require('../lib/common/common').myReturn;

function MaxVersionComparator(e1,e2){
    return new Number(e1.version)-new Number(e2.version);
}
function hide(db,stmt){
    db.updateField(null,stmt,{
        "hide":true
    }, function (err, ret) {
        console.log(ret);
        return(err==null?"true":"false");
    });
}

function upsert(db,stmt,data){
    logger.debug("Try to insert env");
    return new Promise(function(resolve,reject){
        db.updateWithParam(null,stmt, data, function (err, ret) {
            if (err != null){
                console.log(err);
                reject(err);
            }
            else {
                logger.debug("Inserted.");
                resolve(ret);
            }
        });
    });
}

function insert(db,data){
    logger.debug("Try to insert env");
    return new Promise(function(resolve,reject){
        db.insert(null, data, function (err, ret) {
            if (err != null){
                console.log(err);
                reject(err);
            }
            else {
                logger.debug("Inserted.");
                resolve(ret);
            }
        });
    });
}

function get(db,stmt){
    return new Promise(function(resolve,reject){
        db.getWithParam(null,stmt, function (err, ret) {
            if(ret==null||ret.length<=0)
                ret=[];
            jsonUtil(ret);
            resolve(ret);
        });
    });
}

function aggregate(db,stmt){
    return new Promise(function(resolve,reject){
        db.aggregate(null,stmt, function (err, ret) {
            resolve(ret);
        });
    });
}

function getMax(db,stmt,comparator){
    return new Promise(function(resolve,reject){
        get(db,stmt).then(function (ret) {
            var res=ret.getMax(comparator);
            resolve(res);
        })
    });
}

function getAndSend(db,stmt,res){
    get(db,stmt).then(function (val) {
        res.send(val);
    });
}

function getAndSendForConfSets(db,stmt,res){

    var _aggrParam = [
        {
            $match:stmt
        },
        {
            $group:{"_id":"$imageName", "isMarket":{$first:"$isMarket"} ,"versionList":{$addToSet: {"imgVersion":"$imageVersion","files":"$files"} } }
        },
        {
            $project:{"cfgMgrId":"$_id","isMarket":"$isMarket","versionList":"$versionList"}
        }
    ];

    aggregate(db,_aggrParam).then(function (val) {

        res.send(val);
    });
}

function getMaxAndSend(db,stmt,res,comparator,defaultValue){
    getMax(db,stmt,comparator).then(function (val) {
        if(val==null)
            val=defaultValue;
        res.send(val);
    });
}

function getNextVersion(db,stmt){
    return new Promise(function (resolve, reject) {
        logger.debug("Try to getMax history version");
        db.getWithParam(null, stmt, function (err, ret) {
            logger.debug("Callback from appConfigEnv base:");
            if (err != null) {
                logger.debug("Error while getting version:"+err);
                console.log(err);
                reject(err);
            }
            else {
                jsonUtil(ret);
                var maxVersion=ret.getMax(MaxVersionComparator);
                if(maxVersion==null)
                    maxVersion=1;
                else
                    maxVersion=new Number(maxVersion.version)+new Number(1);
                logger.debug("New version:"+maxVersion);
                resolve(""+maxVersion);
            }
        });
    })
}

/*
 * 请求格式{
 *  namespace:<命名空间名>,
 *  name:<环境名，如dev，同一命名空间下可重复>,
 *  imageName:<镜像名>,
 *  [createTime:<创建时间，可提供，但无效>],
 *  value:{
 *   <变量Key-Value对>
 *  }
 *  [hide:<是否隐藏，可提供，但无效>]
 * }
 * 返回值：错误信息|env数据(增加了字段——version：环境量版本)
 */
router.post('/addEnv', function (req, res, next) {
    var env=req.body;
    var namespace=req.username;
    env.namespace=namespace;
    env.createTime=Date.now();
    env.hide=false;
    getNextVersion(envdb,{
        namespace: env.namespace,
        name: env.name,
        imageName: env.imageName
    }).then(function (val) {
        if(val==null){
            reject("error while querying data");
        }
        env.version=val;
        return insert(envdb,env);
    }).then(function (val) {
        res.send(val);
    }).catch(function(err){
        res.send(err);
    });

});
/*
 * 请求格式{
 *  namespace:<命名空间名>,
 *  name:<环境名，如dev>,
 *  imageName:<镜像名>,
 *  [version:<环境量版本，默认为最新版>]
 * }
 * 返回值：错误信息|env数据
 */
router.post('/getEnv', function (req, res, next) {
    var env=req.body;
    var stmt={
        namespace: req.username,
        name: env.name,
        imageName: env.imageName,
        hide:false
    };
    if(env.version!=null)
        stmt.version=env.version;
    getMaxAndSend(envdb,stmt,res,MaxVersionComparator,{});
});
/*
*
*
*/
router.get('/listEnv', function (req, res, next) {
    var env=req.query;
    var stmt={
        namespace: req.username,
        hide:false,
        imageName:env.image,
        imageVersion:env.version
    };
    var resp=[];
    get(setdb,stmt,res).then(function(val){
        return new Promise(function(resolve,reject){
            if(val==[]||val.length<=0)
                reject();
            val=val.shift();
            if(val.envs==undefined||val.envs=={})
                reject();

            for(var name in val.envs){
                resp.push({
                    namespace:req.username,
                    name:name,
                    imageName:env.image,
                    version:env.version,
                    value:val.envs[name]
                });
            }
            resolve(resp);
        });
    }).then(function(val){
        res.send(resp);
        
    }).catch(function(err){
        res.send("[]");
    });
});
/*
 * 请求格式{
 *  namespace:<命名空间名>,
 *  name:<环境名，如dev>,
 *  imageName:<镜像名>,
 *  version:<环境量版本>
 * }
 * 返回值：true|false
 */
router.post('/delEnv', function (req, res, next) {
    var env=req.body;
    var stmt={
        namespace: req.username,
        name: env.name,
        imageName: env.imageName,
        version:env.version
    };
    if(env.version==null)
    {
        res.send("false");
        return;
    }
    return hide(envdb,stmt);
});
/*
 * 参数说明：cfg-参数文件
 * cfg格式{
 *   filepath:<>,
 *   namespace:<>,
 *   imageName:<>,
 *   [createTime:<创建时间，可提供，但无效>],
 *   value:<模板值>
 *   [hide:<是否隐藏，可提供，但无效>]
 * }
 * 返回值：false|cfg数据(增加了字段——version：文件版本)
 */
router.post('/addConfigFile', function (req, res, next) {
    var config=req.body;
    var namespace=req.username;
    config.namespace=namespace;
    config.createTime=Date.now();
    config.hide=false;
    getNextVersion(filedb,{
        namespace: config.namespace,
        filepath: config.filepath,
        imageName: config.imageName
    }).then(function (val) {
        if(val==null){
            reject("error while querying data");
        }
        config.version=val;
        return insert(filedb,config);
    }).then(function (val) {
        res.send(val);
    }).catch(function(err){
        res.send(err);
    });
});

/*
 * 请求格式{
 *   filepath:<>,
 *   namespace:<>,
 *   imageName:<>,
 *  version:<环境量版本>
 * }
 * 返回值：true|false
 */
router.post('/deleteConfigFile', function (req, res, next) {
    var file=req.body;
    var stmt={
        namespace: req.username,
        filepath: file.filepath,
        imageName: file.imageName,
        version:file.version
    };
    if(file.version==null)
    {
        res.send("false");
        return;
    }
    return hide(filedb,stmt);
});
/*
 * 请求格式{
 *   filepath:<>,
 *   namespace:<>,
 *   imageName:<>,
 *  [version:<版本，默认为最新版>]
 * }
 * 返回值：错误信息|配置文件数据
 */
router.post('/getConfigFile', function (req, res, next) {
    var config=req.body;
    var stmt={
        namespace: req.username,
        filepath: config.filepath,
        imageName: config.imageName,
        hide:false
    };
    if(config.version!=null)
        stmt.version=config.version;
    getMaxAndSend(filedb,stmt,res,MaxVersionComparator,{});
});
/* 插入或更新
 * 参数说明：cfs-参数文件集
 * cfs格式{
 *   namespace:<>,
 *   imageName:<>,
 *   imageVersion:<>,
 *   files:[
 *       {
 *           filepath:<>,
 *           version:<>
 *       }
 *   ]
 * }
 * 返回值：false|cfs数据
 */
router.post('/upsertConfigFileSet', function (req, res, next) {
    var data=req.body;
    data.hide=false;
    data.namespace=req.username;

    upsert(setdb,{
        "imageVersion": data.imageVersion,
        "imageName": data.imageName,
        "isMarket":data.isMarket,
        namespace:data.namespace
    },data).then(function (val) {
        res.send(val);
    }).catch(function(err){
        res.send(err);
    });
});

/**
 *  不更新 env
 */
router.post('/udpConfigFileSet', function (req, res, next) {
    var data=req.body;
    data.hide=false;
    data.namespace=req.username;

    var _udpData = {$set:data};

    upsert(setdb,{
        "imageVersion": data.imageVersion,
        "imageName": data.imageName,
        "isMarket":data.isMarket,
        namespace:data.namespace
    },_udpData).then(function (val) {
        res.send(val);
    }).catch(function(err){
        res.send(err);
    });
});

/*
 *
 *
 */
router.get('/listConfigFileSet', function (req, res, next) {
    var env=req.query;
    var stmt={
        namespace: req.username,
        hide:false
    };
    if(env.hasOwnProperty("image")){
        stmt.imageName=env.image;
    }
    getAndSendForConfSets(setdb,stmt,res);
});

router.get('/listConfigFileSetSvc', function (req, res, next) {
    var env=req.query;
    var stmt={
        namespace: req.username,
        hide:false
    };
    if(env.hasOwnProperty("image")){
        stmt.imageName=env.image;
    }
    getAndSend(setdb,stmt,res);
});

router.post('/delImgVerCfg', function (req, res, next) {
    var imageName = req.body.imageName;
    var versions = req.body.imageVersion;
    var files = req.body.files;
    var namespace=req.username;

    var stmt = {
        imageName:imageName,
        imageVersion:{$in:versions}
    }
    setdb.delWithParam(null,stmt,function(err,ret){
        if(err){
            res.send(myRet(false, err.message,err.message));
        }else{
            //add ns and image name
            files.forEach(function(file){
                file.imageName = imageName;
                file.namespace = namespace;
            })
            var _stm = {
                $or:files
            }
            if(files.length === 0 ){
                _stm = {};
            }

            filedb.delWithParam(null,_stm,function(err,ret){
                if(err){
                    res.send(myRet(false, err.message,err.message));
                }else{
                    res.send(myRet(true));
                }
            })
        }
    })
});

router.post('/updateSetEnvs',function(req, res, next){

    var namespace=req.username;
    var stmt = {
        imageName:req.body.imageName,
        imageVersion:req.body.version,
        namespace:namespace
    }

    upsert(setdb,stmt,{$set:{"envs":req.body.envs}}).then(function(val){
        res.send(myRet(true));
    }).catch(function(err){
        res.send(myRet(false,err.message,err.message));
    });;
})

router.post('/ImplConfigFile', function (req, res, next) {
    var imageName=req.body.image.name;
    var version=req.body.image.version;
    var namespace=req.username;
    var envName=req.body.env.name;
    var envVersion=req.body.env.version;
    var x=new cmgr();
    x.implement(imageName,version,namespace,envName,envVersion).then(function (files) {
        res.send(x.getDef(files,imageName));
    }).catch(function (err) {
        res.send(err);
    })
});

router.get('/oneConf', function (req, res, next) {
    var conf=req.query;
    var stmt={
        namespace: req.username,
        serviceName:conf.serviceName,
        version:conf.imageTag
    };
    var resp=[];
    get(historydb,stmt,res).then(function(val){
        return new Promise(function(resolve,reject){
            if(val==[]||val.length<=0)
                reject();
            val=val.shift();
            if(val==undefined||val=={})
                reject();

            resp.push({
                namespace:req.username,
                serviceName:conf.serviceName,
                version:conf.imageTag,
                confName:val.confName
            });
            resolve(resp);
        });
    }).then(function(val){
        res.send(resp);
    }).catch(function(err){
        res.send(err);
    });
});


router.post('/updateConf', function (req, res, next) {
    var conf=req.query;
    upsert(setdb,{
        namespace: conf.username,
        serviceName:conf.serviceName,
        version:conf.imageTag
    },conf).then(function (val) {
        res.send(myRet(true, err.message,val));
    }).catch(function(err){
        res.send(myRet(false, err.message,err.message));
    });
});

module.exports = router;